package de.uni_saarland.coli.doclists.data.btree.manager;

import de.uni_saarland.coli.doclists.data.btree.INode;
import de.uni_saarland.coli.doclists.data.btree.SplitData;
import de.uni_saarland.coli.doclists.data.btree.nodes.BucketNode;
import de.uni_saarland.coli.doclists.data.btree.nodes.NonBucketNode;
import de.uni_saarland.coli.doclists.index.filesystem.CachedObjectDiscList;
import de.uni_saarland.coli.doclists.index.filesystem.IToBytes;

public class DiscBTreeNodeManager<T extends IToBytes> implements
		IBTreeNodeManager<T> {

	private CachedObjectDiscList<INode<T>> nodeCache;
	private CachedObjectDiscList<T> dataCache;

	private static IDataFromByteFactory dataCreator;

	public DiscBTreeNodeManager(int size, IDataFromByteFactory dataFactory) {
		DiscBTreeNodeManager.dataCreator = dataFactory;
		this.nodeCache = new CachedObjectDiscList<INode<T>>(size) {

			@Override
			public INode<T> createObject(byte[] bytes) {
				switch (bytes[0]) {
				case 1:
					return new BucketNode<T>(bytes);
				case 0:
					return new NonBucketNode<T>(bytes);
				default:
					return null;
				}
			}
		};

		this.dataCache = new CachedObjectDiscList<T>(size) {

			@SuppressWarnings("unchecked")
			@Override
			public T createObject(byte[] bytes) {
				return (T) DiscBTreeNodeManager.dataCreator
						.createFromBytes(bytes);
			}
		};
	}

	@Override
	public INode<T> getNode(int id) {
		return this.nodeCache.getObject(id);
	}

	@Override
	public T getValue(int id) {
		return this.dataCache.getObject(id);
	}

	@Override
	public int addValue(T value) {
		this.dataCache.addObject(value);

		return value.getListIDX();
	}

	@Override
	public INode<T> createNonBucketNode() {
		NonBucketNode<T> node = new NonBucketNode<T>();
		this.nodeCache.addObject(node);

		return node;
	}

	@Override
	public INode<T> createNonBucketNode(SplitData<T> data) {
		NonBucketNode<T> node = new NonBucketNode<T>(data);
		this.nodeCache.addObject(node);
		
		return node;
	}

	@Override
	public INode<T> createBucketNode() {
		BucketNode<T> node = new BucketNode<T>();
		this.nodeCache.addObject(node);

		return node;
	}

	@Override
	public void save(String path, String baseName) {
		this.dataCache.save(path, baseName + ".data");
		this.nodeCache.save(path, baseName + ".nodes");

	}

	@Override
	public void open(String path, String baseName) {
		this.dataCache.open(path, baseName + ".data");
		this.nodeCache.open(path, baseName + ".nodes");
	}

	@Override
	public String toString() {
		
		return "nodes:\n" + this.nodeCache.toString() + "\ndata:" + this.dataCache.toString();
	}
}
